#ifndef IBC_NAV_OBJ_H
#define IBC_NAV_OBJ_H

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#ifdef __cplusplus
extern "C"
{
#endif

#define IBCnav_HEAD 0x90EB
#define IBCnav_MAX_LEN 200

#define IBCnav_FUSION_ID 0xD1
#define IBCnav_ORIGIN_ID 0xDA

#ifndef IBCnav_ENABLE_MOBILE_PLATFORM
#define IBCnav_ENABLE_MOBILE_PLATFORM 0
#endif

#pragma pack(push, 1)
  /*INS 融合数据输出*/
  typedef struct IBCnav_fusion_t
  {
    uint16_t head; // 0x90EB
    uint8_t len;
    uint8_t id; // 0xD1

    uint32_t count;

    uint8_t state; // 低3位: ahrs.   0 初始化 1正常 2错误
                   // bit3 罗盘是否需要校准  0 正常   1需要校准
                   // 高四位健康状态
                   // bit4 罗盘     0正常   1故障
                   // bit5  陀螺    0正常   1故障
                   // bit6  加计     0正常   1故障
                   // bit7  气压计    0正常   1故障

    float pitch;   // unit:rad,ahrs   抬头正
    float roll;    // unit:rad,ahrs   右滚正
    float yaw;     // unit:rad,ahrs   N 0    E 90   W -90   S +-180
    float yaw_gps; // unit:d,gps      N 0    E 90   W -90   S +-180

    float pitch_rate; // unit:rad/s,ahrs   抬头正
    float roll_rate;  // unit:rad/s,ahrs   右滚正
    float yaw_rate;   // unit:rad/s,ahrs   顺时针为正

    int32_t lon; // unit:0.0000001d,inertial_nav
    int32_t lat; // unit:0.0000001d,inertial_nav

    int32_t alt_baro; // unit:0.01m,barometer   原始气压高度
    int32_t alt_gps;  // unit:0.01m,gps         原始GPS高度
    int32_t alt;      // unit:0.01m,inertial_nav   EKF滤波高度   无GPS从零开始，有GPS按照GPS高度初始化

    float velocity_x;   // unit:m/s,NED,inertial_nav   N  正
    float velocity_y;   // unit:m/s,NED,inertial_nav   E  正
    float velocity_z;   // unit:m/s,NED,inertial_nav   D  正
    float velocity_air; // m/s,

    float accel_x; // unit:m/s^2,NED,ahrs     N  正
    float accel_y; // unit:m/s^2,NED,ahrs     E  正
    float accel_z; // unit:m/s^2,NED,ahrs     D  正

    uint8_t satellite_num;
    uint16_t hdop; // 0.01m
    uint16_t vdop; // 0.01m

    uint8_t gps_status; // NO_GPS = 0,                     ///< No GPS connected/detected
                        // NO_FIX = 1,                     ///< Receiving valid GPS messages but no lock
                        // GPS_OK_FIX_2D = 2,              ///< Receiving valid messages and 2D lock
                        // GPS_OK_FIX_3D = 3,              ///< Receiving valid messages and 3D lock
                        // GPS_OK_FIX_3D_DGPS = 4,         ///< Receiving valid messages and 3D lock with differential improvements
                        // GPS_OK_FIX_3D_RTK_FLOAT = 5,    ///< Receiving valid messages and 3D RTK Float
                        // GPS_OK_FIX_3D_RTK_FIXED = 6,    ///< Receiving valid messages and 3D RTK Fixed
    uint8_t gps_hh;
    uint8_t gps_mm;
    uint8_t gps_ss;

    int8_t temperature; // d  度
    int16_t HDT;        // d  真航向   0~3600   0~3600度   -17    负值不可用	  单位 0.1度
    int16_t HDG_Dev;    // d  标准差   0~3600   0~3600度   -17    负值不可用	  单位 0.1度

    uint8_t redundancy; //  01 加计  23 陀螺  45 罗盘  67 GPS  0 1 2 3 按优先级 来  加计&陀螺: 0 外部  1内部1 2内部2  罗盘: 0外部 1 内部  GPS: 0内部  1 外部
    uint8_t GPS0_DT;    // 内部   单位100ms  范围 0-255
    uint8_t GPS1_DT;    // 外部   单位100ms  范围 0-255

    float GPS_vx; // unit:m/s,NED,GPS   N  正
    float GPS_vy; // unit:m/s,NED,GPS   E  正
    float GPS_vz; // unit:m/s,NED,GPS   D  正

    uint16_t gps_ms;    // GPSms
    uint8_t gps_day;    // GPS天
    uint16_t gps_week;  // GPS周	1980年1月5日夜晚与1980年1月6日凌晨之间0点。最大时间单位是周（一周：604800秒）。每1024周（即7168天）为一循环周期。第一个GPS周循环点为1999年8月22日0时0分0秒。即从这一刻起，周数重新从0开始算起
    uint8_t ahrs_state; // AHRS 状态（直接置为0即可）  120

#if IBCnav_ENABLE_MOBILE_PLATFORM
    float eastward_dis;  // 东向距离 unit:m
    float northward_dis; // 北向距离 unit:m
    float skyward_dis;   // 天向距离 unit:m
    uint16_t std_dev;    // unit:0.01m
    uint16_t std_dev_up; // unit:0.01m

    uint16_t true_north;   // 真北偏角 unit:0.01°
    uint16_t Ground_speed; // 地速 unit:0.01m
#endif

    uint16_t Engine_RPM; // 发动机转速 单位：rpm
    uint16_t check_sum;
  } IBCnav_FUSION_T;

  /*INS 原始数据输出*/
  typedef struct IBCnav_origin_t
  {
    uint16_t head; // 0x90EB
    uint8_t len;   //
    uint8_t id;    // 0xD3

    uint32_t count;
    uint32_t DIAG_STAT;

    float mainIMU_WX; // x轴角速度
    float mainIMU_WY; // y轴角速度
    float mainIMU_WZ; // z轴角速度

    float mainIMU_FX; // x轴加速度
    float mainIMU_FY; // y轴加速度
    float mainIMU_FZ; // z轴加速度

    float backupIMU_WX; // x轴角速度
    float backupIMU_WY; // y轴角速度
    float backupIMU_WZ; // z轴角速度

    float backupIMU_FX; // x轴加速度
    float backupIMU_FY; // y轴加速度
    float backupIMU_FZ; // z轴加速度

    float MAG_HX; // X轴磁感应强度
    float MAG_HY; // Y轴磁感应强度
    float MAG_HZ; // Z轴磁感应强度

    float GPS_sec;

    double heading;
    uint32_t heading_type;

    double hor_spd;
    double trk_gnd;
    double vert_spd;

    double lat;
    double lon;
    double hgt;

    uint32_t pos_type;
    uint32_t PPS_dt;
    double OBS_GPS_V[3];
    int16_t ZUPT; /* 零速修正 */
    float MG_YAW;
    float MG_yaw_temp;

    uint16_t checksum;
  } IBCnav_ORIGIN_T;
#pragma pack(pop)

  typedef struct IBCnav_obj_t
  {
    IBCnav_FUSION_T fusionData;
    IBCnav_ORIGIN_T originData;

    int step;
    uint16_t tempHeader;
    uint16_t tempLen;
    uint16_t tempLoc;
    uint8_t tempBuf[IBCnav_MAX_LEN];
  } IBCnav_OBJ_t;

  IBCnav_OBJ_t *IBCnav_create(void);
  void IBCnav_destroy(IBCnav_OBJ_t *nav);
  int IBCnav_init(IBCnav_OBJ_t *nav);
  int IBCnav_pushData(IBCnav_OBJ_t *nav, const uint8_t data);
  void IBCnav_prfOriginData(IBCnav_OBJ_t *nav, int (*println)(const char *fmt, ...));
  void IBCnav_prfFusionData(IBCnav_OBJ_t *nav, int (*println)(const char *fmt, ...));

  uint16_t IBCnav_checksum(uint8_t *data, uint8_t len);

#ifdef __cplusplus
}
#endif

#endif
